home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / quest.c < prev    next >
C/C++ Source or Header  |  1993-01-24  |  8KB  |  331 lines

  1. /*    SCCS Id: @(#)quest.c    3.1    92/11/13    */
  2. /*    Copyright 1991, M. Stephenson          */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. #ifdef MULDGN
  8. /*  quest dungeon branch routines. */
  9.  
  10. #include "quest.h"
  11. #include "qtext.h"
  12.  
  13. #define Not_firsttime    (on_level(&u.uz0, &u.uz))
  14. #define Qstat(x)    (quest_status.x)
  15.  
  16. static void NDECL(on_start);
  17. static void NDECL(on_locate);
  18. static void NDECL(on_goal);
  19. static boolean NDECL(not_capable);
  20. static boolean NDECL(not_pure);
  21. static void FDECL(expulsion, (BOOLEAN_P));
  22. static void NDECL(chat_with_leader);
  23. static void NDECL(chat_with_nemesis);
  24. static void NDECL(chat_with_guardian);
  25.  
  26. static void
  27. on_start() {
  28.   if(!Qstat(first_start)) {
  29.     qt_pager(QT_FIRSTTIME);
  30.     Qstat(first_start) = TRUE;
  31.   } else if((u.uz0.dnum != u.uz.dnum) || (u.uz0.dlevel < u.uz.dlevel)) {
  32.     if(Qstat(not_ready) <= 2) qt_pager(QT_NEXTTIME);
  33.     else    qt_pager(QT_OTHERTIME);
  34.   }
  35. }
  36.  
  37. static void
  38. on_locate() {
  39.   if(!Qstat(first_locate)) {
  40.     qt_pager(QT_FIRSTLOCATE);
  41.     Qstat(first_locate) = TRUE;
  42.   } else if(u.uz0.dlevel < u.uz.dlevel)
  43.     qt_pager(QT_NEXTLOCATE);
  44. }
  45.  
  46. static void
  47. on_goal() {
  48.   if(!Qstat(made_goal)) {
  49.     qt_pager(QT_FIRSTGOAL);
  50.     Qstat(made_goal) = 1;
  51.   } else {
  52.     qt_pager(QT_NEXTGOAL);
  53.     if(Qstat(made_goal) < 7) Qstat(made_goal)++;
  54.   }
  55. }
  56.  
  57. void
  58. quest_init() {
  59. /*
  60.  *    Special setup modifications here:
  61.  *
  62.  *    Unfortunately, this is going to have to be done on each level,
  63.  *    on start-up, and on entry, since you lose the permonst mods
  64.  *    across a save/restore :-)
  65.  *
  66.  *    1 - The Rogue Leader is the Tourist Nemesis.
  67.  *    1 - Elves can have one of two different leaders, work it out here.
  68.  *    2 - Priests start with a random alignment - convert the leader and
  69.  *        guardians here.
  70.  */
  71. #ifdef TOURIST
  72.     if(pl_character[0] == 'T' && Is_nemesis(&u.uz)) {
  73.     register struct monst *mtmp;
  74.     mons[PM_MASTER_OF_THIEVES].msound = MS_NEMESIS;
  75.     mons[PM_MASTER_OF_THIEVES].mflags2 &= ~(M2_PEACEFUL);
  76.     mons[PM_MASTER_OF_THIEVES].mflags2 |= (M2_NASTY|M2_STALK|M2_HOSTILE);
  77.     mons[PM_MASTER_OF_THIEVES].mflags3 = M3_WANTSARTI | M3_WAITFORU;
  78.     for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) /* find the leader... */
  79.         if(mtmp->data->msound == MS_NEMESIS) {
  80.         set_malign(mtmp); /* changed M2_PEACEFUL */
  81.         break;
  82.         }
  83.     } else
  84. #endif
  85.     if(pl_character[0] == 'E' && flags.female && Is_qstart(&u.uz)) {
  86.     register struct monst *mtmp;
  87.     for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) /* find the leader... */
  88.         if(mtmp->data->msound == MS_LEADER) {
  89.         mtmp->data = &mons[PM_ELWING]; /* sex-change */
  90.         break;
  91.         }
  92.     } else if(pl_character[0] == 'P' && Is_qstart(&u.uz)) {
  93.  
  94.     register struct monst *mtmp;
  95.     for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) /* find leader & guards */
  96.        if(mtmp->data->msound == MS_LEADER ||
  97.           mtmp->data->msound == MS_GUARDIAN) {
  98.            /* use game-start alignment for reference */
  99.         mtmp->data->maligntyp = u.ualignbase[1]*3;
  100.         mtmp->mpeaceful = TRUE;
  101.         set_malign(mtmp); /* mpeaceful may have changed */
  102.        }
  103.     }
  104. }
  105.  
  106. void
  107. onquest() {
  108.  
  109.     if(Not_firsttime)    return;
  110.     if(!Is_special(&u.uz)) return;
  111.  
  112.     if(Is_qstart(&u.uz)) on_start();
  113.     else if(Is_qlocate(&u.uz) && u.uz.dlevel > u.uz0.dlevel) on_locate();
  114.     else if(Is_nemesis(&u.uz)) on_goal();
  115.     return;
  116. }
  117.  
  118. void
  119. nemdead() {
  120.     if(!Qstat(killed_nemesis)) {
  121.         Qstat(killed_nemesis) = TRUE;
  122.         qt_pager(QT_KILLEDNEM);
  123.     }
  124. }
  125.  
  126. void
  127. artitouch() {
  128.     if(!Qstat(touched_artifact)) {
  129.         Qstat(touched_artifact) = TRUE;
  130.         qt_pager(QT_GOTIT);
  131.         exercise(A_WIS, TRUE);
  132.     }
  133. }
  134.  
  135. /* external hook for do.c (level change check) */
  136. boolean
  137. ok_to_quest() {
  138.  
  139.     return(Qstat(got_quest));
  140. }
  141.  
  142. static boolean
  143. not_capable() {
  144.   return(u.ulevel < MIN_QUEST_LEVEL);
  145. }
  146.  
  147. /* TODO:    This one needs tuning. */
  148. static boolean
  149. not_pure() {
  150. #ifdef WIZARD
  151.     if(wizard && (u.ualign.record < MIN_QUEST_ALIGN)) {
  152.  
  153.        You("are currently %d and require %d.",
  154.          u.ualign.record, MIN_QUEST_ALIGN);
  155.        if(yn_function("adjust?", NULL, 'y') == 'y')
  156.         u.ualign.record = MIN_QUEST_ALIGN;
  157.     }
  158. #endif
  159.   return(u.ualign.record < MIN_QUEST_ALIGN);
  160. }
  161.  
  162. /*
  163.  * Expell the player to the stairs on the parent of the quest dungeon.
  164.  *
  165.  * This assumes that the hero is currently _in_ the quest dungeon and that
  166.  * there is a single branch to and from it.
  167.  */
  168. static void
  169. expulsion(seal)
  170. boolean seal;
  171. {
  172.   branch *br;
  173.   d_level *dest;
  174.  
  175.   br = dungeon_branch("The Quest");
  176.   dest = (br->end1.dnum == u.uz.dnum) ? &br->end2 : &br->end1;
  177.   assign_level(&u.utolev, dest);
  178.   u.utotype = 1; /* portal */
  179.   if (seal) {    /* remove the portal to the quest - sealing it off */
  180.     u.utotype |= 0200;
  181.     u.uevent.qexpelled = 1;
  182.   }
  183. }
  184.  
  185. static void
  186. chat_with_leader()
  187. {
  188. /*    Rule 0:    Cheater checks.                    */
  189.     if(u.uhave.questart && !Qstat(met_nemesis))
  190.         Qstat(cheater) = TRUE;
  191.  
  192. /*    It is possible for you to get the amulet without completing
  193.  *    the quest.  If so, try to induce the player to quest.
  194.  */
  195.     if(Qstat(got_thanks)) {
  196. /*    Rule 1:    You've gone back with/whithout the amulet.    */
  197.             if(u.uhave.amulet)    qt_pager(QT_HASAMULET);
  198.  
  199. /*    Rule 2:    You've gone back before going for the amulet.    */
  200.         else        qt_pager(QT_POSTHANKS);
  201.     }
  202.  
  203. /*    Rule 3: You've got the artifact and are back to return it. */
  204.       else if(u.uhave.questart) {
  205.         if(u.uhave.amulet)    qt_pager(QT_HASAMULET);
  206.         else        qt_pager(QT_OFFEREDIT);
  207.         Qstat(got_thanks) = TRUE;
  208.         u.uevent.qcompleted = 1;    /* you did it! */
  209.  
  210. /*    Rule 4: You haven't got the artifact yet.    */
  211.     } else if(Qstat(got_quest)) qt_pager(rn1(10, QT_ENCOURAGE));
  212.  
  213. /*    Rule 5: You aren't yet acceptable - or are you? */
  214.     else {
  215.       if(!Qstat(met_leader)) {
  216.         qt_pager(QT_FIRSTLEADER);
  217.         Qstat(met_leader) = TRUE;
  218.         Qstat(not_ready) = 0;
  219.       } else qt_pager(QT_NEXTLEADER);
  220.  
  221.       if(not_capable()) {
  222.         qt_pager(QT_BADLEVEL);
  223.         exercise(A_WIS, TRUE);
  224.         expulsion(FALSE);
  225.       } else if(not_pure()) {
  226.         qt_pager(QT_BADALIGN);
  227.         if(Qstat(not_ready) == MAX_QUEST_TRIES) {
  228.           qt_pager(QT_LASTLEADER);
  229.           expulsion(TRUE);
  230.         } else {
  231.           Qstat(not_ready)++;
  232.           exercise(A_WIS, TRUE);
  233.           expulsion(FALSE);
  234.         }
  235.       } else {    /* You are worthy! */
  236.         qt_pager(QT_ASSIGNQUEST);
  237.         exercise(A_WIS, TRUE);
  238.         Qstat(got_quest) = TRUE;
  239.       }
  240.     }
  241. }
  242.  
  243. void
  244. leader_speaks(mtmp)
  245.  
  246.     register struct monst *mtmp;
  247. {
  248.     /* maybe you attacked leader? */
  249.     if(!mtmp->mpeaceful) {
  250.         Qstat(pissed_off) = TRUE;
  251.         mtmp->data->mflags3 = 0;    /* end the inaction */
  252.     }
  253.  
  254.         if(Qstat(pissed_off)) {
  255.       qt_pager(QT_LASTLEADER);
  256.       expulsion(TRUE);
  257.     } else chat_with_leader();
  258.  
  259. }
  260.  
  261. static void
  262. chat_with_nemesis()
  263. {
  264. /*    The nemesis will do most of the talking, but... */
  265.         qt_pager(rn1(10, QT_DISCOURAGE));
  266.     if(!Qstat(met_nemesis)) Qstat(met_nemesis++);
  267. }
  268.  
  269. void
  270. nemesis_speaks()
  271. {
  272.     if(!Qstat(in_battle)) {
  273.       if(u.uhave.questart) qt_pager(QT_NEMWANTSIT);
  274.       else if(!Qstat(made_goal)) qt_pager(QT_FIRSTNEMESIS);
  275.       else if(Qstat(made_goal) < 3) qt_pager(QT_NEXTNEMESIS);
  276.       else if(Qstat(made_goal) < 7) qt_pager(QT_OTHERNEMESIS);
  277.       else if(!rn2(5))    qt_pager(rn1(10, QT_DISCOURAGE));
  278.       if(Qstat(made_goal) < 7) Qstat(made_goal)++;
  279.        Qstat(met_nemesis) = TRUE;
  280.     } else /* he will spit out random maledictions */
  281.       if(!rn2(5))    qt_pager(rn1(10, QT_DISCOURAGE));
  282. }
  283.  
  284. static void
  285. chat_with_guardian()
  286. {
  287. /*    These guys/gals really don't have much to say... */
  288.         qt_pager(rn1(5, QT_GUARDTALK));
  289. }
  290.  
  291. void
  292. quest_chat(mtmp)
  293.  
  294.     register struct monst *mtmp;
  295. {
  296.  
  297.     switch(mtmp->data->msound) {
  298.         case MS_LEADER:    chat_with_leader(); break;
  299.         case MS_NEMESIS:    chat_with_nemesis(); break;
  300.         case MS_GUARDIAN:    chat_with_guardian(); break;
  301.         default:    impossible("quest_chat: Unknown quest character %s.",
  302.                    mon_nam(mtmp));
  303.     }
  304. }
  305.  
  306. void
  307. quest_talk(mtmp)
  308.  
  309.     register struct monst *mtmp;
  310. {
  311.     switch(mtmp->data->msound) {
  312.         case MS_LEADER:    leader_speaks(mtmp); break;
  313.         case MS_NEMESIS:    nemesis_speaks(); break;
  314.         default:        break;
  315.     }
  316. }
  317.  
  318. void
  319. quest_stat_check(mtmp)
  320.  
  321.     struct monst *mtmp;
  322. {
  323.     if(mtmp->data->msound == MS_NEMESIS)
  324.     Qstat(in_battle) = 
  325.         (mtmp->mcanmove && !mtmp->msleep && monnear(mtmp, u.ux, u.uy));
  326. }
  327.  
  328. #endif /* MULDGN */
  329.  
  330. /*quest.c*/
  331.